<?php
declare (strict_types = 1);
namespace app\promotion\logic;

use app\common\exception\LogicException;
use app\common\model\ShareCode;
use app\promotion\model\PromotionBargain as PromotionBargainModel;
use think\facade\Request;
use think\facade\Db;
use app\common\command\algorithm\Bargain as BargainAlgorithm;

/**
 * 砍价逻辑层
 */
class PromotionBargain extends PromotionBargainModel
{

    protected $hiddenColumn = [];

    public function __construct()
    {
        $this->hiddenColumn = array_merge(app(Promotion::class)->getHiddenColumn(), ['type', 'discount']);
    }
    
    /**
     * 检查用户是否存在砍价
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date 2021-04-08
     * @param  int    $promotion_id [description]
     * @return [type]               [description]
     */
    public function existSponsorBargain(int $promotion_id): bool
    {
        $data = $this->sponsor()->promotionId($promotion_id)->findOrEmpty();

        return !$data->isEmpty();
    }

    /**
     * 获取当前用户指定课程砍价详情
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date 2021-04-08
     * @param  int    $promotion_id [description]
     * @return [type]               [description]
     */
    public function getSponsorBargainInfo(int $promotion_id, int $sponsor_user_id = 0)
    {
        if (!$sponsor_user_id) {
            $sponsor_user_id = ShareCode::getShareUser() ? : request()->mid; 
        }

        $sql = $this->where('promotion_id',$promotion_id)->where('sponsor_user_id',$sponsor_user_id)->buildSql();
        $exist = Db::query($sql);

        if ( !$exist ) {
            $promotion = app(Promotion::class)->with(['product_info'])->findOrEmpty($promotion_id);
            bcscale(2);
            $re = $this::create([
                'promotion_id'      => $promotion_id,
                'sponsor_user_id'   => $sponsor_user_id,
                'remain_price'      => bcsub($promotion->product_price.'',$promotion->price.''),
                'remain_nums'       => $promotion->num,
                'create_time'       => Request::time(),
            ]);
            if ( $re->isEmpty() ) throw new LogicException("数据错误，请重试");
        }

        $data = app(Promotion::class)
            ->with([
                'product_info',
                'bargain' => function($query) use ($sponsor_user_id) {
                    $query
                        ->sponsor($sponsor_user_id)
                        ->withCount([
                            'current_bargain' => function($query) {
                                $query->where('current_user_id', request()->mid);
                            }
                        ])
                        ->with([
                            'current_bargain' => function($query) {
                                $query->where('current_user_id', request()->mid);
                            },
                            'bargain_data'
                        ])
                        ->bind([
                            'sponsor_user_id',
                            'current_bargain_count',
                            'bargain_id' => 'id',
                            'current_bargain_price',
                            'bargained_nums',
                            'bargained_total_price',
                            'bargain_finished' => 'done',
                            'bargain_data',
                        ])
                    ;
                }
            ])
            ->findOrEmpty($promotion_id)
            ->append(['running_status', 'start_countdown', 'end_countdown', 'type_text'])
            ->hidden($this->hiddenColumn)
        ;
        bcscale(2);
        $data->bargain_price    = bcsub($data->product_price.'', $data->price.'')*1;
        $data->remain_price     = bcsub($data->bargain_price.'', $data->bargained_total_price.'')*1;
        $data->remain_nums      = $data->num - $data->bargained_nums;

        return $data;
    }

    /**
     * 执行砍价操作
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date 2021-04-12
     * @param  [type] $param [description]
     * @return [type]        [description]
     */
    public function doBargain($param)
    {
        // 验证数据
        $this->getValidate()->scene('do_bargian')->failException()->check($param);
        // 参数
        $promotion_id       = intval($param['promotion_id']);
        $sponsor_user_id    = intval($param['sponsor_user_id']);
        // 检查活动过期
        $promotion = app(Promotion::class)->findOrEmpty($promotion_id);
        if ($promotion->isEmpty()) throw new LogicException("活动已结束");
        // 
        if (request()->mid == $sponsor_user_id) throw new LogicException("不能为自己砍价");
        //
        $promotion = $this->getSponsorBargainInfo($promotion_id, $sponsor_user_id);
        //
        if ( $promotion->current_bargain_count ) throw new LogicException("已经帮好友砍价，不能重复砍价");
        if ( !$promotion->remain_nums || !$promotion->remain_price) throw new LogicException("好友砍价已完成，无需帮砍");

        Db::startTrans();

        try {

            $money = app(BargainAlgorithm::class)->getBargainMoney($promotion->remain_nums, $promotion->remain_price);

            bcscale(2);
            $update = [
                'bargained_nums'        => $promotion->bargained_nums + 1,
                'bargained_total_price' => bcadd($promotion->bargained_total_price.'', $money['bargain_price'].''),
                'remain_price'          => $money['remain_price'],
                'remain_nums'           => $money['remain_nums'],
                'done'                  => $money['remain_nums']?0:1,
            ];
            // $aaaa = $this->sponsor($sponsor_user_id)->promotionId($promotion_id)->lock(true)->findOrEmpty();
            // halt($aaaa);
            $re = Db::name('promotion_bargain')->where('id', $promotion->bargain_id)->update($update);

            if ( !$re ) throw new LogicException("砍价失败..");

            $create_data = [
                'bargain_id'            => $promotion->bargain_id,
                'current_user_id'       => request()->mid,
                'current_bargain_price' => $money['bargain_price']
            ];

            $bargain_data = PromotionBargainData::create($create_data);

            if ( $bargain_data->isEmpty() ) throw new LogicException("砍价失败...");

            Db::commit();

            return $this->getSponsorBargainInfo($promotion_id, $sponsor_user_id);

        } catch (LogicException $e) {
            Db::rollback();
            throw new LogicException($e->getMessage());
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }
    }

    /**
     * 删除用户砍价信息，用于取消订单
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date 2021-06-08
     */
    public function deleteUserBargain(int $promotion_id, int $user_id)
    {
        $data = $this->wherePromotionId($promotion_id)->whereSponsorUserId($user_id)->findOrEmpty();
        if ( !$data->isEmpty() ) {
            $item = app(PromotionBargainData::class)->whereBargainId($data->id)->select();
            if ( !$item->isEmpty() ) {
                if ( !$item->delete() ) throw new LogicException('删除失败');
            }
            if ( !$data->delete() ) throw new LogicException('删除失败');
        }
    }

}
